package com.example.codereview;


import com.example.codereview.git.GitService;
import com.example.codereview.review.CodeLight;
import com.example.codereview.review.ReviewChat;
import com.example.codereview.review.ReviewContent;
import com.example.codereview.swing.CustomJTextPane;
import com.example.codereview.util.DateUtils;
import com.example.codereview.util.IdeaUtils;
import com.example.codereview.util.JavaCodeStyle;
import com.example.codereview.util.ObjectUtils;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBScrollPane;

import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.example.codereview.review.ReviewConstant.REVIEW_DIR_PATH;

public class ReviewDialog extends JDialog implements ActionListener, MouseListener {

    private JButton confirm, cancel;
    private Project project;
    private AnActionEvent e;
    private ReviewContent reviewContent;
    private GitService gitService = new GitService();
    private int lineNum;
    private String branchName;
    private String modulePath;
    private String username;
    private String codeReviewPath;
    private String filePath;
    private String fileName;
    private String code;
    private List<ReviewContent> reviewContents;
    private ComboBox<String> comboBox;
    private JTextPane codeEditor;
    private List<CodeLight> codeLights = new ArrayList<>();

    private CustomJTextPane reviewArea;
    private CustomJTextPane handleArea;


    /**
     * 操作 1 查看 2 添加 3 修改 4 处理
     */
    private int operate;

    /**
     * 初始化git相关信息
     */
    private void initBaseMsg(){
        //项目
        this.project = e.getProject();
        //模块路径
        this.modulePath = IdeaUtils.getModuleFilePath(e);
        //当前git用户
        this.username = gitService.getUser(this.modulePath);
        //当前文件路径
        VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if(!ObjectUtils.isEmpty(file)){
            this.filePath = file.getPath();
            this.fileName = file.getName();
        }
        //模块分支名称
        this.branchName = gitService.branchName(modulePath);
        if (this.branchName.contains("/")) {
            this.branchName = this.branchName.replaceAll("/","-");
        }
        //代码评审路径
        this.codeReviewPath = modulePath + REVIEW_DIR_PATH + "/" + branchName+".ser";
        //当前点击所在行号
        Editor editor = e.getData(PlatformDataKeys.EDITOR);
        if (project != null && editor != null) {
            // 获取光标所在行号
            this.lineNum = editor.getCaretModel().getLogicalPosition().line + 1; // 行号从1开始计数
        }
        //初始化代码评审内容，如果当前文件当前行数有，则赋值
        this.reviewContents  = IdeaUtils.parseObject(codeReviewPath);
        if(!ObjectUtils.isEmpty(reviewContents)){
            this.reviewContent = reviewContents.stream().filter(r -> r.getPath().equals(filePath) && r.getNumber() == lineNum)
                    .findFirst().orElse(null);
            if(!ObjectUtils.isEmpty(reviewContent)){
                this.codeLights = this.reviewContent.getLights();
                this.codeLights.forEach(c -> {
                    System.out.println("codeLights: "+c.getOffset());
                });
            }
        }else{
            this.reviewContents = new ArrayList<>();
        }
        if(ObjectUtils.isEmpty(reviewContent)){
            this.reviewContent = new ReviewContent();
            this.reviewContent.setReviewId(IdeaUtils.uuid());
            this.reviewContent.setCreateTime(new Date());
            this.reviewContent.setAuthor(username);
            this.reviewContent.setCodeContent(code);
            this.reviewContent.setFileName(fileName);
            this.reviewContent.setNumber(lineNum);
            this.reviewContent.setPath(filePath);
            this.reviewContent.setStatus(1);
            this.reviewContent.setChats(new ArrayList<>());
            this.reviewContents.add(this.reviewContent);
        }
    }

    private ComboBox<String> initComboBox(){
        // 创建一个 ComboBox 的模型
        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();

        // 添加选项
        List<String> authors = gitService.getAuthors(modulePath);
        for(String author : authors){
            model.addElement(author);
        }
        // 创建 ComboBox 组件
        ComboBox<String> comboBox = new ComboBox<>(model);

        // 设置选择事件监听器
        comboBox.addActionListener(e -> {
            String author = (String) comboBox.getSelectedItem();
            this.reviewContent.setCodeAuthor(author);
        });
        if(!ObjectUtils.isEmpty(this.reviewContent.getCodeAuthor())){
            comboBox.setSelectedItem(this.reviewContent.getCodeAuthor());
        }
        return comboBox;
    }

    public ReviewDialog(AnActionEvent e,int operate,String code){
        this.e = e;
        this.code = code;
        this.operate = operate;
        //初始化基础信息
        initBaseMsg();
        setModal(true);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        int width = 850;
        int height = 290;
        setSize(width, height);
        setLayout(null);
        setTitle("code review");


        // 创建表单组件
        JLabel label1 = new JLabel("评价人:  ",SwingConstants.RIGHT);
        label1.setBounds(10,10,60,30);
        JLabel label11 = new JLabel(this.reviewContent.getAuthor());
        label11.setBounds(80,10,150,30);

        JLabel label12 = new JLabel("行号:  ");
        label12.setBounds(240,10,50,30);
        JLabel label121 = new JLabel(this.lineNum+"行");
        label121.setBounds(290,10,100,30);
        label121.setForeground(JBColor.RED);

        this.add(label1);
        this.add(label11);
        this.add(label12);
        this.add(label121);

        if(this.reviewContent.getStatus() == 2) {
            JLabel labelJiejue = new JLabel("已解决");
            labelJiejue.setForeground(JBColor.GREEN);
            labelJiejue.setBounds(400, 10, 200, 35);
            this.add(labelJiejue);
        }

        String time = DateUtils.dateToStrLong(this.reviewContent.getCreateTime() == null ? new Date() : this.reviewContent.getCreateTime());
        JLabel label2 = new JLabel("评价时间:  ",SwingConstants.RIGHT);
        label2.setBounds(10,50,60,30);
        JLabel label22 = new JLabel(time);
        label22.setBounds(80,50,150,30);
        this.add(label2);
        this.add(label22);

        //指派人
        JLabel zhipaiLabel = new JLabel("指派人:  ",SwingConstants.RIGHT);
        zhipaiLabel.setBounds(10,90,60,30);
        ComboBox<String> comboBox = initComboBox();
        comboBox.setBounds(80,90,100,30);

        //相关代码
        JLabel codeLabel = new JLabel("相关代码",SwingConstants.RIGHT);
        codeLabel.setBounds(10,130,60,30);
        this.add(codeLabel);
        this.codeEditor = new JTextPane(){
            @Override
            public boolean getScrollableTracksViewportWidth() {
                // 返回false表示不跟踪视口宽度，避免自动换行
                return false;
            }
        };
        codeEditor.setBounds(80,140,720,200);
        codeEditor.setEditable(true);
        JavaCodeStyle.setText(codeEditor, this.reviewContent.getCodeContent(),this.codeLights);
        StyleContext styleContext = StyleContext.getDefaultStyleContext();
        AttributeSet redAttributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, JBColor.RED);
        ((AbstractDocument) codeEditor.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
                super.insertString(fb, offset, string, redAttributeSet); // 使用红色样式插入字符串
            }
            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                //将集合中offset大于等于当前offset的数据都+1
                System.out.println("replace offset: "+offset);
                codeLights.forEach(c->{
                    if(c.getOffset() >= offset){
                        c.setOffset(c.getOffset()+1);
                    }
                });
                Document doc = fb.getDocument();
                Element root = doc.getDefaultRootElement();
                int currentLineIndex = root.getElementIndex(offset);
                int currentLineNumber = currentLineIndex + 1; // 行号从1开始计数
                CodeLight light = new CodeLight();
                light.setOffset(offset);
                light.setValue(text);
                light.setLineNumber(currentLineNumber);
                codeLights.add(light);
                super.replace(fb, offset, length, text, redAttributeSet); // 使用红色样式替换文本
            }

            @Override
            public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
                //将集合中offset大于等于当前offset的数据都-1
                System.out.println("remove offset: "+offset);
                codeLights.removeIf(c->offset == c.getOffset());
                codeLights.forEach(c->{
                    if(c.getOffset() >= offset){
                        c.setOffset(c.getOffset()-1);
                    }
                });

                super.remove(fb, offset, length);
            }
        });
        JBScrollPane codeScrollPane = new JBScrollPane(codeEditor,
                JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        codeScrollPane.setBounds(80, 140, 720, 200);
        this.add(codeScrollPane);

        JLabel label = new JLabel("评审内容:  ", SwingConstants.RIGHT);
        label.setBounds(10, 340, 60, 30);
        reviewArea = new CustomJTextPane();
        reviewArea.setBounds(80, 350, 720, 100);
        if (reviewContent.getContent() != null) {
            reviewArea.deSerializeContent(reviewContent.getContent());
        }
        reviewArea.setName("reviewContent");
        if (this.operate == 1 || this.operate == 4) {
            //查看下不可编辑
            reviewArea.setEditable(false);
            comboBox.setEnabled(false);
        }

        JBScrollPane contentScrollPane = new JBScrollPane(reviewArea,
                JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        contentScrollPane.setBounds(80, 350, 720, 100);

        int y = 460;

        if (operate == 1 || operate == 4) {
            JLabel label3 = new JLabel("解决人:  ", SwingConstants.RIGHT);
            label3.setBounds(10, 460, 60, 30);

            JLabel label33 = new JLabel();
            label33.setBounds(80, 460, 150, 30);

            JLabel label4 = new JLabel("解决内容:  ", SwingConstants.RIGHT);
            label4.setBounds(10, 500, 60, 50);
            handleArea = new CustomJTextPane();
            handleArea.setBounds(80, 505, 720, 60);
            handleArea.setName("handleContent");
            JBScrollPane handScrollPane = new JBScrollPane(handleArea,
                    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            handScrollPane.setBounds(80, 505, 720, 100);
            if (operate == 1) {
                handleArea.setEditable(false);
            }
            if (operate == 1 && !ObjectUtils.isEmpty(reviewContent.getChats())) {
                ReviewChat reviewChat = reviewContent.getChats().get(0);
                label33.setText(reviewChat.getAuthor());
                handleArea.deSerializeContent(reviewChat.getMsg());
            } else if (operate == 4) {
                label33.setText(username);
            }
            y = 610;
            this.add(label3);
            this.add(label33);
            this.add(label4);
            this.add(handScrollPane);
        }

        this.add(label1);
        this.add(label2);
        this.add(zhipaiLabel);
        this.add(comboBox);
        this.add(label);
        this.add(contentScrollPane);

        confirm = new JButton("确定");
        confirm.setBounds(745, y, 60, 25);
        confirm.addActionListener(this);

        cancel = new JButton("取消");
        cancel.setBounds(665, y, 60, 25);
        cancel.addActionListener(this);

        if (this.operate == 2 || this.operate == 3) {
            //查看下不可编辑
            JButton pastImage = new JButton("粘贴图片");
            pastImage.setBounds(585, y, 60, 25);
            pastImage.addActionListener(actionEvent -> {
                reviewArea.pasteImage();
            });
            this.add(pastImage);
        }
        if (this.operate == 4) {
            //查看下不可编辑
            JButton pastImage = new JButton("粘贴图片");
            pastImage.setBounds(585, y, 60, 25);
            pastImage.addActionListener(actionEvent -> {
                handleArea.pasteImage();
            });
            this.add(pastImage);
        }
        this.add(cancel);
        this.add(confirm);
        setSize(width, y + 80);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == this.cancel) {
            this.dispose();
        } else if (e.getSource() == this.confirm) {
            if (operate == 1) {
                this.dispose();
                return;
            }
            if (operate == 4) {
                reviewContent.setHandler(username);
                reviewContent.setHandleTime(new Date());
                reviewContent.setStatus(2);
                //存储解决内容里面的值
                CustomJTextPane.JTextPaneContent jTextPaneContent = handleArea.serializeContent();
                ReviewChat chat = new ReviewChat();
                chat.setAuthor(username);
                chat.setCreateTime(new Date());
                chat.setMsg(jTextPaneContent);
                reviewContent.setChats(Collections.singletonList(chat));
                if (handleArea.getStyledDocument().getLength() == 0) {
                    JOptionPane.showMessageDialog(this, "请填写解决内容！", "提示", JOptionPane.WARNING_MESSAGE);
                    return;
                }
            }
            if (operate == 2 || operate == 3) {
                CustomJTextPane.JTextPaneContent jTextPaneContent = reviewArea.serializeContent();
                reviewContent.setContent(jTextPaneContent);
                if (reviewArea.getStyledDocument().getLength() == 0) {
                    JOptionPane.showMessageDialog(this, "请填写评审内容！", "提示", JOptionPane.WARNING_MESSAGE);
                    return;
                }
            }
            if (operate == 3) {
                this.reviewContent.setStatus(1);
            }

            this.reviewContent.setLights(this.codeLights);
            IdeaUtils.createDir(modulePath + REVIEW_DIR_PATH);
            IdeaUtils.writeObject(this.reviewContents, codeReviewPath);
            if (reviewContent.getStatus() == 2) {
                IdeaUtils.addGutterIcon(project, this.reviewContent.getAuthor() + ": " + this.reviewContent.getContent(), this.reviewContent.getNumber(), 2);
            } else if (reviewContent.getStatus() == 1) {
                IdeaUtils.addGutterIcon(project, this.reviewContent.getAuthor() + ": " + this.reviewContent.getContent(), this.reviewContent.getNumber(), 1);
            }
            ReviewView reviewView = ReviewSidebarFrame.getReviewView();
            if (!ObjectUtils.isEmpty(reviewView)) {
                reviewView.refresh();
            }
            this.dispose();
        }
    }


    public static void main(String[] args) {
        String value = "}\n" +
                "        return1";
        System.out.println();
    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}
